﻿using GameLibrary;
using Microsoft.Xna.Framework;
using Rescue_of_the_Dwarvenzombies.GameStates;
using Rescue_of_the_Dwarvenzombies.Scene.Levels;
using Rescue_of_the_Dwarvenzombies.SceneLayers;
using Rescue_of_the_Dwarvenzombies.SceneObjects;

namespace Rescue_of_the_Dwarvenzombies.Scene
{
    /// <summary>
    /// The Scene Managers responsibility is to keep all parts of the game engine updated
    /// </summary>
    internal class SceneManager : GameComponent, ISceneManager
    {
        /// <summary>
        /// Reference to the Game State Manager
        /// </summary>
        private GameStateManager _gameStateManager;

        /// <summary>
        /// Reference to the Sound Manager
        /// </summary>
        private SoundManager soundManager;

        /// <summary>
        /// Reference to the current level
        /// </summary>
        private Level level;
        //private List<Level> levels;

        /// <summary>
        /// Gets or sets the current state
        /// </summary>
        public GameState CurrentState { get; set; }

        /// <summary>
        /// Initializes a new instance of the SceneManager class.
        /// </summary>
        /// <param name="game">The game.</param>
        /// <param name="graphics">The graphics.</param>
        public SceneManager(Game game, GraphicsDeviceManager graphics)
            : base(game)
        {
            game.Services.AddService(typeof(ISceneManager), this);

            level = new Level1();
            game.Services.AddService(typeof(ILevel), level);

            Camera camera = new Camera(game.GraphicsDevice.Viewport, graphics);
            game.Services.AddService(typeof(ICamera), camera);

            soundManager = new SoundManager(game);
            game.Services.AddService(typeof(ISoundManager), soundManager);

            _gameStateManager = new GameStateManager(game);
            CurrentState = _gameStateManager.CurrentState;
        }

        /// <summary>
        /// Called when the Scene Manager needs to be updated. The call is handled in its current state.
        /// </summary>
        /// <param name="gameTime">Time elapsed since the last call to Update</param>
        public override void Update(GameTime gameTime)
        {
            CurrentState.Update(gameTime);
        }

        /// <summary>
        /// Gets the root layer.
        /// </summary>
        /// <returns>The root layer</returns>
        public ISceneLayer GetRootLayer()
        {
            return CurrentState.RootLayer;
        }

        /// <summary>
        /// Used when the Physics Manager detects a collision with more complex consequences
        /// </summary>
        /// <param name="currentSceneObject">The current scene object.</param>
        /// <param name="childObject">The child object.</param>
        /// <param name="parentLayer">The parent layer.</param>
        /// <param name="childLayer">The child layer.</param>
        public void HandleCollision(ISceneObject currentSceneObject, ISceneObject childObject, ISceneLayer parentLayer, ISceneLayer childLayer)
        {
            ((PlayingState)CurrentState).HandleCollision(currentSceneObject, childObject, parentLayer, childLayer);
        }

        /// <summary>
        /// Gets the average player positions.
        /// </summary>
        /// <returns>A vector2 indicating the average X and Y coordinates</returns>
        public Vector2 GetAvgPlayerPositions()
        {
            return ((PlayingState)CurrentState).AveragePlayerPositions;
        }

        /// <summary>
        /// Restarts the level.
        /// </summary>
        public void RestartLevel()
        {
            ((PlayingState)CurrentState).RestartLevel();
        }

        /// <summary>
        /// Gets the spawn positions of the current level.
        /// </summary>
        /// <returns>A vector2 with the coordinates of the spaws positions</returns>
        public Vector2[] GetSpawnPositions()
        {
            return level.GetSpawningPositions();
        }

        /// <summary>
        /// Gets the number of enemies in the current level.
        /// </summary>
        /// <returns>the number of enemies</returns>
        public int GetNumberOfEnemies()
        {
            return level.GetAmountOfEnemies();
        }
    }
}